package com.totem.admin.controller;

import cn.hutool.crypto.asymmetric.RSA;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.totem.admin.api.AdminServiceApi;
import com.totem.admin.service.AdminService;
import com.totem.admin.service.IEmailService;
import com.totem.admin.service.ITAppConfigService;
import com.totem.admin.service.ITIssueService;
import com.totem.admin.vo.*;
import com.totem.base.CacheHolder;
import com.totem.base.constants.CacheConstants;
import com.totem.base.constants.CommonConstants;
import com.totem.base.constants.ErrorCode;
import com.totem.base.constants.SecurityComponets;
import com.totem.base.enums.LoginTypeEnum;
import com.totem.base.exception.BaseException;
import com.totem.base.model.Result;
import com.totem.base.util.RandomValueUtils;
import com.totem.base.util.SmsUtil;
import com.totem.customer.mapper.TCustomerMapper;
import com.totem.customer.model.TCustomers;
import com.totem.customer.vo.GlobalConfigCacheVO;
import com.totem.startup.InitialGlobalConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executor;

@Slf4j
@RestController
public class AdminController implements AdminServiceApi {
    private static final boolean encryptEnable = CommonConstants.ENCRYPT_ENABLE;
    private static final RSA rsa = SecurityComponets.DEFAULT_ENCRYPTOR;
    @Autowired
    private ITIssueService itIssueService;
    @Autowired
    private ITAppConfigService itAppConfigService;
    @Autowired
    private IEmailService iEmailService;
    @Autowired
    private Executor asyncExecutor;
    @Autowired
    private TCustomerMapper tCustomerMapper;
    @Autowired
    private AdminService adminService;
    @Autowired
    private CacheHolder cacheHolder;

    private String loginUsername = "METAHOME";
    private String loginPassword = "metahome111";
    private String smsUsername = "metahome";
    private String apiKey = "729f7b89128343dfa796bbb1a08ad527";
    @Override
    public Result<ServerConfigVO> systemConfig() {
        String publicKeyBase64 = rsa.getPublicKeyBase64();
        String privateKeyBase64 = rsa.getPrivateKeyBase64();
        if(log.isDebugEnabled()) {
            log.debug("encryptEnable:{}, publicKey:{}", encryptEnable, publicKeyBase64);
        }
        String pemPublicKey = "-----BEGIN PUBLIC KEY-----";
        pemPublicKey +=publicKeyBase64;
        pemPublicKey += "-----END PUBLIC KEY-----";
        ServerConfigVO vo = new ServerConfigVO();
        vo.setEncrypt(encryptEnable);
        vo.setAppId(CommonConstants.APP_ID);
        vo.setPublicKey(publicKeyBase64);
        //vo.setPrivateKey(privateKeyBase64);
        return Result.success(vo);
    }

    @Override
    public Result<AppConfigListVO> appConfig() {
        return Result.success(itAppConfigService.findAll());
    }

    @Override
    public Result<GlobalConfigCacheVO> globalConfigCache() {
        InitialGlobalConfig instance = InitialGlobalConfig.instance();
        GlobalConfigCacheVO cacheVO = new GlobalConfigCacheVO();
        BeanUtils.copyProperties(instance, cacheVO);
        return Result.success(cacheVO);
    }

    @Override
    public Result<Boolean> updateSubscribeConfig(UpdateSubscribeVO updateSubscribeVO) {
        return Result.success(itAppConfigService.updateSubscribeConfig(updateSubscribeVO));
    }

    @Override
    public Result<Boolean> updateAppConfig(AppConfigVO appConfigVO) {
        return Result.success(itAppConfigService.updateAppConfig(appConfigVO));
    }

    @Override
    public Result<Boolean> submitIssue(SubmitIssueVO vo) {
        return Result.success(itIssueService.save(vo));
    }

    @Override
    public Result<VerificationCodeVO> verificationCode(VerificationCodeVO vo) {
        String loginType = vo.getLoginType();
        LoginTypeEnum loginTypeEnum = LoginTypeEnum.byCode(loginType);
        if(loginTypeEnum==null){
            throw new BaseException(ErrorCode.ILLEGAL_LOGIN_TYPE);
        }
        boolean newCustomer = vo.getNewCustomer();

        String tempCode = RandomValueUtils.random(6, false, true);
        Object usableCountObj = cacheHolder.get(tempCode);
        while(usableCountObj!=null && (Long)usableCountObj>0){
            tempCode = RandomValueUtils.random(6, false, true);
            usableCountObj = cacheHolder.get(tempCode);
        }
        final String code = tempCode;

        if(LoginTypeEnum.isMobile(loginType)){
            String countryCode = vo.getCountryCode();
            String content = null;
            if("86".equalsIgnoreCase(countryCode)){
                content = String.format("【METAHOMO】您的验证码是%s。如非本人操作，请忽略本短信", code);
            }else{
                content = String.format("【METAHOMO】Your verification code is %s. If not operated by oneself, please ignore this message", code);
            }
            content = SmsUtil.encodeUrlString(content, StandardCharsets.UTF_8.name());
            String mobile = vo.getMobile();
            if(StringUtils.isBlank(countryCode) || StringUtils.isBlank(mobile)){
                throw new BaseException(ErrorCode.REQUIRED_MOBILE);
            }
            if(!newCustomer) {
                LambdaQueryWrapper<TCustomers> custQuery = new LambdaQueryWrapper<>();
                custQuery.eq(TCustomers::getCountryCode, countryCode);
                custQuery.eq(TCustomers::getMobile, mobile);
                TCustomers one = tCustomerMapper.selectOne(custQuery);
                if (one == null) {
                    throw new BaseException(ErrorCode.NOT_EXIST_CUSTOMER);
                }
                vo.setCustomerId(one.getId());
            }

            String httpUrl = null;
            StringBuffer httpArg = new StringBuffer();
            httpArg.append("u=").append(smsUsername).append("&");
            httpArg.append("p=").append(apiKey).append("&");
            httpArg.append("c=").append(content).append("&");
            if("86".equalsIgnoreCase(countryCode)){
                httpUrl = "http://api.smsbao.com/sms";
                httpArg.append("m=").append(mobile);
            }else{
                httpUrl = "http://api.smsbao.com/wsms";
                mobile = countryCode+mobile;
                String encodeMobile = SmsUtil.encodeUrlString("+"+mobile, StandardCharsets.UTF_8.name());
                httpArg.append("m=").append(encodeMobile);
            }
            String key = CacheConstants.CACHE_VERIFICATION_CODE+mobile;
            String countKey = CacheConstants.CACHE_VERIFICATION_COUNT+mobile;
            cacheHolder.set(key, code, CacheConstants.CODE_EXPIRE_MS);
            cacheHolder.set(countKey, CacheConstants.VERIFY_USABLE_COUNT, CacheConstants.CODE_EXPIRE_MS);
            //log.info("向[{}]设置验证码:[{}]", key, code);
            String s = SmsUtil.request(httpUrl, httpArg.toString());
            if("0".equalsIgnoreCase(s)) {
                log.info("短信成功发送到{}-{}", vo.getCountryCode(), vo.getMobile());
                vo.setCode(code);
            }else{
                log.warn("短信发送错误: {}-{}", vo.getCountryCode(), vo.getMobile());
                throw new BaseException(ErrorCode.ERROR);
            }
        }
        if(LoginTypeEnum.isEmail(loginType)){
            String email = vo.getEmail();
            if(StringUtils.isBlank(email)){
                throw new BaseException(ErrorCode.REQUIRED_EMAIL);
            }
            if(!newCustomer) {
                LambdaQueryWrapper<TCustomers> custQuery = new LambdaQueryWrapper<>();
                custQuery.eq(TCustomers::getEmail, email);
                TCustomers one = tCustomerMapper.selectOne(custQuery);
                if (one == null) {
                    throw new BaseException(ErrorCode.NOT_EXIST_CUSTOMER);
                }
                vo.setCustomerId(one.getId());
            }
            String key = CacheConstants.CACHE_VERIFICATION_CODE+email;
            String countKey = CacheConstants.CACHE_VERIFICATION_COUNT+email;
            cacheHolder.set(key, code, CacheConstants.CODE_EXPIRE_MS);
            cacheHolder.set(countKey, CacheConstants.VERIFY_USABLE_COUNT, CacheConstants.CODE_EXPIRE_MS);
            //log.info("向[{}]设置验证码:[{}]", key, code);
            asyncExecutor.execute(()->
                iEmailService.sendSeniorEmail(email, "Verification Code", "Your verification code is:" + code, true)
            );
            vo.setCode(code);
        }
        vo.setCodeExpireTime(CacheConstants.CODE_EXPIRE_MS);
        vo.setVerifyUsableCount(CacheConstants.VERIFY_USABLE_COUNT);
        return Result.success(vo);
    }

    @Override
    public Result<VerificationCodeCheckVO> verificationCodeCheck(VerificationCodeCheckVO vo) {
        String loginType = vo.getLoginType();
        LoginTypeEnum loginTypeEnum = LoginTypeEnum.byCode(loginType);
        if(loginTypeEnum==null){
            throw new BaseException(ErrorCode.ILLEGAL_LOGIN_TYPE);
        }
        boolean checkResult = false;
        String inputCode = vo.getInputCode();
        if(StringUtils.isBlank(inputCode)){
            throw new BaseException(ErrorCode.REQUIRED_VERIFICATION_CODE);
        }
        if(LoginTypeEnum.isMobile(loginType)){
            String countryCode = vo.getCountryCode();
            String mobile = vo.getMobile();
            if(StringUtils.isBlank(countryCode) || StringUtils.isBlank(mobile)){
                throw new BaseException(ErrorCode.REQUIRED_MOBILE);
            }
            if(!"86".equalsIgnoreCase(countryCode)) {
                mobile = countryCode + mobile;
            }
            String key = CacheConstants.CACHE_VERIFICATION_CODE+mobile;
            String countKey = CacheConstants.CACHE_VERIFICATION_COUNT+mobile;
            Object value = cacheHolder.get(key);
            //log.info("从[{}]获取验证码:[{}], 输入验证码:[{}]", key, value, inputCode);
            if(value!=null){
                checkResult = inputCode.equals(value.toString());
            }
            cacheHolder.decr(countKey, 1);
        }
        if(LoginTypeEnum.isEmail(loginType)){
            String email = vo.getEmail();
            if(StringUtils.isBlank(email)){
                throw new BaseException(ErrorCode.REQUIRED_EMAIL);
            }
            String key = CacheConstants.CACHE_VERIFICATION_CODE+email;
            String countKey = CacheConstants.CACHE_VERIFICATION_COUNT+email;
            Object value = cacheHolder.get(key);
            //log.info("从[{}]获取验证码:[{}], 输入验证码:[{}]", key, value, inputCode);
            if(value!=null){
                checkResult = inputCode.equals(value.toString());
            }
            cacheHolder.decr(countKey, 1);
        }
        vo.setCheckResult(checkResult);
        return Result.success(vo);
    }

    @Override
    public Result<FirstPageVO> firstPage() {
        return Result.success(adminService.firstPage());
    }
}

